/* Pically
 * Copyright (C) 2011 Petros Dolaschjan.  All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package de.pd.pically.gui;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SortOrder;
import javax.swing.table.DefaultTableModel;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.application.Action;
import org.jdesktop.application.Application;
import org.jdesktop.application.ApplicationActionMap;
import org.jdesktop.application.FrameView;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.HighlighterFactory;

import com.sun.codemodel.internal.JOp;

import de.pd.pically.bean.CalendarEventBean;
import de.pd.pically.bean.CalendarEventBean.EventType;
import de.pd.pically.bean.CalendarEventContainer;
import de.pd.pically.bean.Pojo;
import de.pd.pically.gui.dialog.ImportIcalDialog;
import de.pd.pically.util.CalCreator;
import de.pd.pically.util.EventStorageUtil;
import de.pd.pically.util.UserSession;
import de.pd.pically.util.Utils;

/**
 * @author petros
 * 
 */
public class PicallyView extends FrameView {

	private JPanel mPanPicsCont;

	// lists
	private DefaultTableModel mEventModel = new DefaultTableModel();

	private JTextField mTfEventText;

	private JComboBox mEventTypeCombo;
	private JComboBox mEventDayCombo;
	private JComboBox mEventMonthCombo;
	
	// the event container
	CalendarEventContainer mEventCont = new CalendarEventContainer();

	private JXTable mEventTable;

	private JComboBox mCbYears;

	/**
	 * @param pApplication
	 */
	public PicallyView(Application pApplication) {
		super(pApplication);

		initFrame();
	}

	/**
	 * 
	 */
	private void initFrame() {
		ApplicationActionMap actionMap = Application.getInstance().getContext()
				.getActionMap(this);
		// -------------------
		// the frame
		getFrame().setPreferredSize(new Dimension(900, 600));
		getFrame().setResizable(false);
		getFrame().setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		getFrame().pack();
		getFrame().setLocationRelativeTo(null);
		Container contentPane = getFrame().getContentPane();
		contentPane.setLayout(new GridLayout(0, 1, 0, 0));
		JPanel panelMain = new JPanel();
		panelMain.setPreferredSize(new Dimension(getFrame().getWidth(),
				getFrame().getHeight()));
		panelMain.setLayout(new MigLayout("wrap 1, fill, ins 0, gap 0",
				"[grow]", "[250px][250px][80px]"));
		contentPane.add(panelMain);

		// -------------------
		// pictures
		//JXTitledPanel panPics = new JXTitledPanel("Months and Pictures");
		
		mPanPicsCont = new JPanel();
		//panPics.setContentContainer(mPanPicsCont);
		mPanPicsCont.setLayout(new MigLayout("wrap 6, fill, ins 0, gap 2px", "[grow]", "[grow]"));
		JTabbedPane tpMonths = new JTabbedPane();
		
		tpMonths.addTab("Months", mPanPicsCont);

		// generate the months
		for (int ii = 0; ii <= 11; ii++) {
			mPanPicsCont.add(new MonthPicPanel(ii), "grow");
		}

		panelMain.add(mPanPicsCont, "grow");
		// -------------------
		// events
		//JXTitledPanel panEvents = new JXTitledPanel("Events");

		JPanel eventsCont = new JPanel();
		eventsCont.setLayout(new MigLayout("wrap 2, fill, ins 10, gap 0",
				"[grow][150px]", "[50px][grow]"));
		
		JTabbedPane tpEvents = new JTabbedPane();
		tpEvents.addTab("Events", eventsCont);
		panelMain.add(tpEvents, "grow");

		// labels
		eventsCont.add(new JLabel("Event Type: "), "cell 0 0");
		mEventTypeCombo = new JComboBox(CalendarEventBean.getAllEventTypes());
		eventsCont.add(mEventTypeCombo, "width 200px, cell 0 0");

		// generate the days
		Integer[] days = new Integer[31];
		for (int day = 0; day < 31; day++) {
			days[day] = new Integer(day + 1);
		}
		eventsCont.add(new JLabel("Day: "), "cell 0 0");
		mEventDayCombo = new JComboBox(days);
		mEventDayCombo.setToolTipText("The day of the event");
		eventsCont.add(mEventDayCombo, "width 20px, cell 0 0");

		// generate the months
		Integer[] months = new Integer[12];
		for (int month = 0; month < 12; month++) {
			months[month] = new Integer(month + 1);
		}
		eventsCont.add(new JLabel("Month: "), "cell 0 0");
		mEventMonthCombo = new JComboBox(months);
		mEventMonthCombo.setToolTipText("The month of the event");
		eventsCont.add(mEventMonthCombo, "width 20px, cell 0 0");

		eventsCont.add(new JLabel("Text: "), "cell 0 0");
		mTfEventText = new JTextField();
		mTfEventText.setToolTipText("The text to be displayed in the calendar");
		eventsCont.add(mTfEventText, "width 200px, cell 0 0");

		// add button
		JButton btnAddEvt = new JButton(actionMap.get("addEventAction"));
		btnAddEvt.setText("Add Event");
		eventsCont.add(btnAddEvt, "cell 0 0");
		
		// buttons on the right side of the table
		JPanel panRightBtns = new JPanel();
		panRightBtns.setLayout(new MigLayout("wrap 1"));
		// remove button
		JButton btnDelEvt = new JButton(actionMap.get("delEventAction"));
		btnDelEvt.setText("Delete Event");
		panRightBtns.add(btnDelEvt);
		//import button
		JButton btnImportEvt = new JButton(actionMap.get("importAction"));
		btnImportEvt.setText("Import iCal");
		panRightBtns.add(btnImportEvt);
		eventsCont.add(panRightBtns, "cell 1 1");
		
		

		mEventTable = new JXTable(mEventModel);
		mEventTable.setEditable(true);
		mEventTable.setSortable(true);
		mEventTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
		mEventTable.setHorizontalScrollEnabled(true);
		mEventTable.setColumnControlVisible(true);
		mEventTable.setShowGrid(true);
		mEventTable.setHighlighters((HighlighterFactory.createSimpleStriping()));
		mEventTable.setAutoResizeMode(JXTable.AUTO_RESIZE_ALL_COLUMNS);
		mEventTable.packAll();

		mEventModel.setColumnIdentifiers(new String[] { "Day", "Month",
				"Text", "Type" });
		JScrollPane spEvent = new JScrollPane(mEventTable);
		eventsCont.add(spEvent, "growx, cell 0 1");
		
		mEventTable.setSortOrder(0, SortOrder.ASCENDING);
		mEventTable.setSortOrder(1, SortOrder.ASCENDING);
		

		// -------------------
		// actions
		//JXTitledPanel panActions = new JXTitledPanel("Actions");

		JPanel actionCont = new JPanel();
		actionCont.setLayout(new FlowLayout(FlowLayout.CENTER));
		//panActions.setContentContainer(actionCont);
		
		// year dropdown
		Integer[] years = new Integer[] { 2011, 2012, 2013, 2014, 2015 };
		mCbYears = new JComboBox(years);
		actionCont.add(mCbYears);
		
		// gen button
		JTabbedPane tabActions = new JTabbedPane();
		PTitlePanel panActions = new PTitlePanel("Actions", actionCont);
		tabActions.addTab("Actions", actionCont);
		panelMain.add(tabActions, "grow");

		JButton btnGenerate = new JButton(actionMap.get("generateAction"));
		btnGenerate.setText("Generate");
		btnGenerate.setBackground(new Color(208, 225, 255));
		actionCont.add(btnGenerate);
		
		// load the stored events
		loadCalendarEvents();
		
		// add window listener
		getFrame().addWindowListener(new WindowAdapter() {

			@Override
			public void windowClosing(WindowEvent pArg0) {
				System.out.println("Saving events");
				EventStorageUtil.saveEventContainer(mEventCont);
			}
			
		});
		// TEST ZONE
	}

	@Action
	public void generateAction() {
		String[] months = new String[12];
		for (int ii = 0; ii < months.length; ii++) {
			MonthPicPanel mpp = (MonthPicPanel) mPanPicsCont.getComponent(ii);
			months[ii] = mpp.getImgPath();
		}

		// prepare the event container
		prepareEventContainer();
		
		
	    JFileChooser fileChooser = new JFileChooser(System.getProperty("user.home"));  
	    int selection = fileChooser.showSaveDialog(null);
	    String targetFile = "";
	    if (selection == JFileChooser.APPROVE_OPTION) {
	    	targetFile = fileChooser.getSelectedFile().getAbsolutePath();
			if(!targetFile.toLowerCase().endsWith("pdf")) {
				targetFile += ".pdf";
			}
		}
	    
	    CalCreator cc = new CalCreator();
	    int selYear = (Integer) mCbYears.getSelectedItem();
	    if(targetFile.length() > 0) {
	    	try {
				cc.createPdf(months, selYear, mEventCont ,targetFile);
				JOptionPane.showMessageDialog(getFrame(), "Your calendar for the year " + selYear + " has been successfully created!");
				int answer = JOptionPane.showConfirmDialog(getFrame(), "Are you happy with Pically? Do you want to make a donation?", "Donation?", JOptionPane.OK_OPTION);
				if(answer == JOptionPane.OK_OPTION) {
					Utils.openURL("https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=96CK5NLX3J9MJ");
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				showErrorMessage("Unexpected Error", "Please check the log output for details");
			}
	    		
	    	
	    }
	    
	}

	/**
	 * 
	 */
	private void prepareEventContainer() {
		mEventCont.clear();
		Vector dataVector = mEventModel.getDataVector();
		for (int row = 0; row < mEventModel.getRowCount(); row++) {
			Vector col = (Vector)dataVector.get(row);
			
			Pojo day = (Pojo)col.get(0);
			
			Pojo month = (Pojo)col.get(1);
			
			String text = (String)col.get(2);
			
			EventType type = (EventType)col.get(3);
			
			CalendarEventBean ceb = new CalendarEventBean(type,
					(Integer)day.getRealValue(), (Integer)month.getRealValue(), text);
			mEventCont.addEvent(ceb);
		}
	}

	@Action
	public void addEventAction() {
		EventType type = (EventType) mEventTypeCombo.getSelectedItem();
		Integer day = (Integer) mEventDayCombo.getSelectedItem();
		Integer month = (Integer) mEventMonthCombo.getSelectedItem();
		String text = mTfEventText.getText();

		if (!validateEventForm())
			return;

		addEvent(type, day, month, text);	
	}

	/**
	 * @param type
	 * @param day
	 * @param month
	 * @param text
	 */
	private void addEvent(EventType et, Integer day, Integer month, String text) {
		String dStr = (day.intValue() < 10) ? "0" + day: "" +  day;
		String mStr = (month.intValue() < 10) ? "0" + month: "" +  month;
		Pojo dayPojo = new Pojo(day, dStr);
		Pojo monthPojo = new Pojo(month, mStr + " " + Utils.getMonthName(month.intValue() - 1));
		mEventModel.addRow(new Object[] { dayPojo, monthPojo, text, et });
		prepareEventContainer();
	}
	
	@Action
	public void delEventAction() {
		if(mEventTable.getSelectedRow() < 0) return;
		int[] selectedRows = mEventTable.getSelectedRows();
		for(int ii = 0; ii < selectedRows.length; ii++) {
			mEventModel.removeRow(mEventTable.getSelectedRow());
		}
		
	}
	
	@Action
	public void importAction() {
		ImportIcalDialog iid = new ImportIcalDialog(getFrame());
		iid.setVisible(true);
		iid.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosed(WindowEvent e) {
            	if(UserSession.lastImportEvents != null) {
	    			for (CalendarEventBean event : UserSession.lastImportEvents) {
	    				addEvent(event.getEventType(), event.getDay(), event.getMonth(), event.getText());
	    			}
	    			UserSession.lastImportEvents = null;
            	}
            }
        });
	}

	private boolean validateEventForm() {
		String text = mTfEventText.getText();
		if (Utils.isStringEmpty(text)) {
			showErrorMessage("Error", "Please enter a text");
			return false;
		}
		return true;
	}
	
	/**
	 * @param pTitle
	 * @param pText
	 */
	private void showErrorMessage(String pTitle, String pText) {
		JOptionPane.showMessageDialog(getFrame(), pText, pTitle,
				JOptionPane.ERROR_MESSAGE);
	}
	
	private void loadCalendarEvents() {
		ArrayList<CalendarEventBean> events = EventStorageUtil.getEventContainer().getAllEvents();
		for (CalendarEventBean event : events) {
			addEvent(event.getEventType(), event.getDay(), event.getMonth(), event.getText());
		}
	}
}
